package server

import (
	"fmt"
	"sync"
)

type PlayerMap struct {
	mutex   sync.RWMutex
	players map[string]*Player
}

func NewPlayerMap() *PlayerMap {
	return &PlayerMap{players: make(map[string]*Player)}
}

func (m *PlayerMap) Len() int {
	m.mutex.RLock()
	defer m.mutex.RUnlock()
	return len(m.players)
}

func (m *PlayerMap) Store(id string, player *Player) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	m.players[id] = player
}

func (m *PlayerMap) Load(id string) (*Player, bool) {
	m.mutex.RLock()
	defer m.mutex.RUnlock()
	player, exist := m.players[id]
	return player, exist
}

func (m *PlayerMap) Del(id string) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	delete(m.players, id)
}

func (m *PlayerMap) Keys() []string {
	var retval []string
	for id, _ := range m.players {
		retval = append(retval, id)
	}
	return retval
}

func (m *PlayerMap) Foreach(fn func(string, *Player)) {
	m.mutex.RLock()
	defer m.mutex.RUnlock()
	for id, player := range m.players {
		fn(id, player)
	}
}

func (m *PlayerMap) ToUsers() []*UserInfoEntry {
	var us []*UserInfoEntry
	m.Foreach(func(s string, player *Player) {
		us = append(us, player.UserInfo.ToUserInfoEntry())
	})
	return us
}

func (m *PlayerMap) ToClubs() []*ClubInfoEntry {
	var clubs []*ClubInfoEntry
	m.Foreach(func(s string, player *Player) {
		clubs = append(clubs, player.CurrentClub.ToClubInfoEntry())
	})
	return clubs
}

func (m *PlayerMap) String() string {
	m.mutex.RLock()
	defer m.mutex.RUnlock()
	return fmt.Sprintf("%v", m.players)
}

func (m *PlayerMap) Exist(id string) bool {
	m.mutex.RLock()
	defer m.mutex.RUnlock()
	_, exist := m.players[id]
	return exist
}
